package com.xbongbong.pro.service.cool.app;

import com.alibaba.dingtalk.openapi.exception.OApiException;
import com.alibaba.dingtalk.openapi.helper.AuthHelper;
import com.alibaba.dingtalk.openapi.helper.DingCoolAppHelper;
import com.alibaba.dingtalk.openapi.helper.Env;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessNodeTaskEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.process.ProcessSummaryHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessNodeTaskModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.pojo.ItemDataPoJo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.StartProcessDTO;
import com.xbongbong.paas.pojo.dto.SummaryDataDTO;
import com.xbongbong.paas.pojo.vo.StartProcessVO;
import com.xbongbong.paas.pojo.vo.SummaryDataVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.util.URLEncodeUtils;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.coolapp.pojo.CardDataPojo;
import com.xbongbong.pro.coolapp.pojo.CardDataProcessNode;
import com.xbongbong.pro.coolapp.pojo.CardDataProcessRecord;
import com.xbongbong.pro.coolapp.pojo.CardDataProcessUpdatePojo;
import com.xbongbong.pro.coolapp.pojo.CardProcessWorkflowPojo;
import com.xbongbong.pro.coolapp.pojo.dto.CoolAppSendCardDTO;
import com.xbongbong.pro.coolapp.pojo.dto.CoolAppWorkflowCardDTO;
import com.xbongbong.pro.enums.coolapp.enums.CardTypeEnum;
import com.xbongbong.pro.enums.coolapp.enums.CardUseSceneEnum;
import com.xbongbong.pro.enums.coolapp.enums.TopCardTypeEnum;
import com.xbongbong.pro.enums.errorcodes.CoolAppErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.CoolAppConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.CoolAppCardDataEntity;
import com.xbongbong.saas.domain.entity.CoolAppCardTemplateEntity;
import com.xbongbong.saas.domain.entity.DingBundleEntity;
import com.xbongbong.saas.enums.DingtalkPageUrlEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.mini.DingBundleStatusEnum;
import com.xbongbong.saas.enums.mini.DingBundleTypeEnum;
import com.xbongbong.saas.model.CoolAppCardDataModel;
import com.xbongbong.saas.model.CoolAppCardTemplateModel;
import com.xbongbong.saas.model.DingBundleModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.util.CoolAppCardUtil;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

/**
 * @author 吴峰
 * @date 2022/08/12 15:12
 */
@Service("coolAppProcessCardService")
public class CoolAppProcessCardServiceImpl implements CoolAppProcessCardService {

    private static final Logger LOG = LoggerFactory.getLogger(CoolAppProcessCardServiceImpl.class);

    @Resource
    private CoolAppCardDataModel coolAppCardDataModel;
    @Resource
    private DingBundleModel dingBundleModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private CoolAppCardTemplateModel coolAppCardTemplateModel;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasProcessNodeTaskModel paasProcessNodeTaskModel;
    @Resource
    private DingCoolAppHelper dingCoolAppHelper;
    @Resource
    private AuthHelper authHelper;
    @Resource
    private BizManagerHelp bizManagerHelp;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private ProcessSummaryHelp processSummaryHelp;


    @Override
    public void coolAppCard(StartProcessDTO startProcessDTO, StartProcessVO startProcessVO) {
        if (Objects.equals(startProcessVO.getNoApprovalRequired(), BasicConstant.ZERO) && Objects.nonNull(startProcessDTO.getOpenConversationId())) {
            Runnable runnable = () -> {
                try {
                    CoolAppWorkflowCardDTO coolAppWorkflowCardDTO = new CoolAppWorkflowCardDTO(startProcessDTO.getCorpid(), startProcessDTO.getLoginUser(), PlatFormEnum.INTERNAL.getValue(),
                            startProcessDTO.getOpenConversationId(), startProcessDTO.getAppId(), startProcessDTO.getMenuId(), startProcessDTO.getFormId(), startProcessDTO.getSaasMark(),
                            startProcessDTO.getBusinessType(), startProcessVO.getTaskId(), null, null, FlowStatusEnum.APPROVAL_PENDING.getType(), TaskTypeEnum.COMMIT.getType());

                    sendProcessCard(coolAppWorkflowCardDTO);
                } catch (Exception e) {
                    LOG.error("发送互动卡片失败", e);
                }
            };
            threadPoolBeanConfig.interactiveCardThreadPool().execute(runnable);
        }
    }


    @Override
    public BaseVO sendProcessCard(CoolAppWorkflowCardDTO coolAppWorkflowCardDTO) throws XbbException {
        // 酷应用：钉钉平台特性
        if (!coolAppWorkflowCardDTO.getCorpid().startsWith("ding")) {
            return new BaseVO();
        }
        String corpid = coolAppWorkflowCardDTO.getCorpid();
        Integer businessType = coolAppWorkflowCardDTO.getBusinessType();
        String userId = coolAppWorkflowCardDTO.getUserId();
        String openConversationId = coolAppWorkflowCardDTO.getOpenConversationId();
        openConversationId = CoolAppCardUtil.decodeOpenConversationId(openConversationId);
        coolAppWorkflowCardDTO.setOpenConversationId(openConversationId);
        Long taskId = coolAppWorkflowCardDTO.getTaskId();
        // 群id不能为空
        if (StringUtil.isEmpty(openConversationId)) {
            throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520001);
        }
        // 酷应用：不能为空或卸载
        DingBundleEntity dingBundleEntity = dingBundleModel.getByType(corpid, openConversationId, DingBundleTypeEnum.COOL_APP.getCode());
        if (Objects.isNull(dingBundleEntity) || Objects.equals(dingBundleEntity.getStatus(), DingBundleStatusEnum.DISMISS.getCode())) {
            throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520002);
        }
        // 只有客户、合同、跟进记录、跟进记录评论回复
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        boolean noNeedCardFlag = !(xbbRefTypeEnum == XbbRefTypeEnum.CUSTOMER_MANAGEMENT || xbbRefTypeEnum == XbbRefTypeEnum.CONTRACT || xbbRefTypeEnum == XbbRefTypeEnum.CUSTOMER_COMMUNICATE
                || xbbRefTypeEnum == XbbRefTypeEnum.SALES_OPPORTUNITY || xbbRefTypeEnum == XbbRefTypeEnum.COMMUNICATE_PLAN || xbbRefTypeEnum == XbbRefTypeEnum.WORK_REPORT);
        if (noNeedCardFlag) {
            throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520003);
        }
        // 使用场景
        CardUseSceneEnum cardUseSceneEnum = CardUseSceneEnum.PROCESS_OR_WORKFLOW;
        // 卡片类型：互动 || 审批工作流吊顶

        boolean workFlow = commonHelp.isOpenWorkFlow(corpid);

        CardProcessWorkflowPojo cardProcessWorkflowPojo = getProcessOrWorkflow(coolAppWorkflowCardDTO, workFlow, false);
        CardDataProcessNode processNode = cardProcessWorkflowPojo.getProcessNode();
        // 审批提交人、审批抄送人、审批人
        Set<String> userIds = new HashSet<>();
        userIds.add(cardProcessWorkflowPojo.getStartNodeUserId());
        userIds.addAll(cardProcessWorkflowPojo.getMainUserIds());
        userIds.addAll(cardProcessWorkflowPojo.getCcUserIds());

        CoolAppCardTemplateEntity cardTemplateEntity = coolAppCardTemplateModel.getByUseScene(CardTypeEnum.IM_CARD.getType(), cardUseSceneEnum.getType());
        CoolAppCardTemplateEntity topTemplateEntity = coolAppCardTemplateModel.getByUseScene(CardTypeEnum.TOP_CARD.getType(), cardUseSceneEnum.getType());

        //保存卡片数据
        CoolAppCardDataEntity cardDataEntity;
        CoolAppCardDataEntity topCardDataEntity;

        CoolAppSendCardDTO coolAppSendCardDTO = new CoolAppSendCardDTO();
        BeanUtil.copyProperties(coolAppWorkflowCardDTO, coolAppSendCardDTO);
        coolAppSendCardDTO.setProcessTaskId(taskId);
        coolAppSendCardDTO.setProcessNodeTaskId(cardProcessWorkflowPojo.getProcessNodeTaskId());
        // 设置审批状态为1(待审批)
        coolAppSendCardDTO.setFlowStatus(FlowStatusEnum.APPROVAL_PENDING.getType());

        cardDataEntity = saveCardData(coolAppSendCardDTO, cardTemplateEntity.getCardId(), JSONArray.parseArray(JSON.toJSONString(userIds)), userId, null,null, JsonHelperUtil.parseObject(JSONObject.toJSONString(processNode)));
        topCardDataEntity = saveCardData(coolAppSendCardDTO, topTemplateEntity.getCardId(),JSONArray.parseArray(JSON.toJSONString(cardProcessWorkflowPojo.getMainUserIds())), userId, cardDataEntity.getCardBizId(),null, JsonHelperUtil.parseObject(JSONObject.toJSONString(processNode)));

        if (CollectionsUtil.isNotEmpty(userIds)) {
            sendProcessOrWorkflow(corpid, cardDataEntity, topCardDataEntity, coolAppSendCardDTO, cardProcessWorkflowPojo);
        }

        return new BaseVO();
    }

    /**
     * 发送审批卡片
     *
     * @param corpid
     * @param cardDataEntity
     * @param topCardDataEntity
     * @param coolAppSendCardDTO
     * @param cardProcessWorkflowPojo
     */
    @Override
    public void sendProcessOrWorkflow(String corpid, CoolAppCardDataEntity cardDataEntity, CoolAppCardDataEntity topCardDataEntity,
                                      CoolAppSendCardDTO coolAppSendCardDTO, CardProcessWorkflowPojo cardProcessWorkflowPojo) {
        Runnable runnable = () -> {
            try {
                String accessToken;
                try {
                    accessToken = authHelper.getAccessToken(corpid);
                } catch (OApiException e) {
                    return;
                }
                String openConversationId = null;
                if (Objects.nonNull(cardDataEntity) && Objects.nonNull(cardDataEntity.getOpenConversationId())) {
                    openConversationId = cardDataEntity.getOpenConversationId();
                } else if (Objects.nonNull(topCardDataEntity) && Objects.nonNull(topCardDataEntity.getOpenConversationId())) {
                    openConversationId = topCardDataEntity.getOpenConversationId();
                }
                if (Objects.isNull(openConversationId)) {
                    throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520001);
                }
                // 获取群成员
                List<String> groupMembers = dingCoolAppHelper.getGroupMembers(accessToken, openConversationId, proBaseConfig.getCoolAppCode());
                if (CollectionsUtil.isEmpty(groupMembers)) {
                    throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520005);
                }
                // 是否是全群成员
//                boolean isAll = Objects.equals(mainUserIds.size(), groupMembers.size()) && groupMembers.size() > BasicConstant.ZERO;

                // 互动卡片
                if (Objects.nonNull(cardDataEntity)) {
                    List<String> commonUserIds = cardDataEntity.getReceiverUserIds().toJavaList(String.class);
                    commonUserIds.retainAll(groupMembers);
                    // 卡片接收人为空
                    if (CollectionsUtil.isEmpty(commonUserIds)) {
                        throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520005);
                    }

                    CardDataPojo commonCardDataPojo = getProcessOrWorkflowCardData(corpid, cardDataEntity, coolAppSendCardDTO, cardProcessWorkflowPojo, commonUserIds, false, null);
                    if (Objects.nonNull(commonCardDataPojo)) {
                        String processQueryKey = bizManagerHelp.sendCard(accessToken, cardDataEntity, commonCardDataPojo);
                        if (Objects.nonNull(processQueryKey)) {
                            cardDataEntity.setProcessQueryKey(processQueryKey);
                            coolAppCardDataModel.update(cardDataEntity);
                        }
                    }
                }

                // 吊顶卡片
                if (Objects.nonNull(topCardDataEntity)) {
                    List<String> mainUserIds = topCardDataEntity.getReceiverUserIds().toJavaList(String.class);
                    mainUserIds.retainAll(groupMembers);
                    // 卡片接收人为空
                    if (CollectionsUtil.isEmpty(mainUserIds)) {
                        throw new XbbException(CoolAppErrorCodeEnum.API_ERROR_1520005);
                    }

                    CardDataPojo topCardDataPojo = getProcessOrWorkflowCardData(corpid , topCardDataEntity, coolAppSendCardDTO, cardProcessWorkflowPojo, mainUserIds, true, null);
                    if (Objects.nonNull(topCardDataPojo)) {
                        String processQueryKey = bizManagerHelp.sendTopCard(accessToken, topCardDataEntity, topCardDataPojo);
                        if (Objects.nonNull(processQueryKey)) {
                            topCardDataEntity.setProcessQueryKey(processQueryKey);
                            coolAppCardDataModel.update(topCardDataEntity);
                        }
                    }
                }

            } catch (XbbException e) {
                LOG.error("发送互动卡片失败XbbException", e);
            } catch (Exception e) {
                LOG.error("发送互动卡片失败Exception", e);
            }
        };
        threadPoolBeanConfig.interactiveCardThreadPool().execute(runnable);
    }


    /**
     * 获取审批卡片数据
     *
     * @param corpid
     * @param cardDataEntity
     * @param coolAppSendCardDTO
     * @param cardProcessWorkflowPojo
     * @param receiverUserIdList
     * @param topCardFlag
     * @param updatePojo
     * @return
     */
    @Override
    public CardDataPojo getProcessOrWorkflowCardData(String corpid, CoolAppCardDataEntity cardDataEntity, CoolAppSendCardDTO coolAppSendCardDTO,
                                                     CardProcessWorkflowPojo cardProcessWorkflowPojo, List<String> receiverUserIdList, boolean topCardFlag, CardDataProcessUpdatePojo updatePojo) throws XbbException {

        Map<String, Object> mainProcessNodeTaskMap = cardProcessWorkflowPojo.getMainProcessMap();
        Map<String, Object> ccProcessNodeTaskMap = cardProcessWorkflowPojo.getCcProcessMap();
        boolean workFlow = cardProcessWorkflowPojo.getWorkflow();
        Object startNodeTask = cardProcessWorkflowPojo.getStartNodeTask();

        boolean notMainNodeFlag = Objects.isNull(mainProcessNodeTaskMap) || mainProcessNodeTaskMap.isEmpty();
        boolean notCcNodeFlag = Objects.isNull(ccProcessNodeTaskMap) || ccProcessNodeTaskMap.isEmpty();

        if (notMainNodeFlag && notCcNodeFlag) {
            return null;
        }
        // 获取审批数据
        PaasProcessDataEntity processDataEntity = new PaasProcessDataEntity();
        PaasProcessTaskEntity paasProcessTaskEntity = new PaasProcessTaskEntity();

        PaasFormExplainEntity paasFormExplainEntity;
        PaasFormEntityExt formEntityExt;
        List<FieldPermissionEntityExt> summaryEntityList;

        // 获取表单解释
        try {
            paasFormExplainEntity = paasFormExplainModel.getByFormId(coolAppSendCardDTO.getFormId(), corpid);
        } catch (XbbException e) {
            paasFormExplainEntity = null;
        }
        // 获取表单
        try {
            formEntityExt = paasFormModel.getByKey(coolAppSendCardDTO.getFormId(), corpid);
        } catch (Exception e) {
            formEntityExt = null;
        }

        // 审批节点直接取前面查到的节点
        Long templateNodeId = getTemplateNodeId(cardDataEntity.getProcessNodeTaskId(), mainProcessNodeTaskMap, ccProcessNodeTaskMap, notMainNodeFlag, notCcNodeFlag);

        if (workFlow) {
            //任务表
            WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(cardDataEntity.getProcessTaskId(), corpid);
            if (workflowTaskEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
            }
            //查询主表数据
            List<PaasFormDataEntityExt> formDataList = formDataHelp.getByDataIdList(Sets.newHashSet(cardDataEntity.getDataId()), workflowTaskEntity.getBusinessType(),
                    workflowTaskEntity.getSaasMark(), workflowTaskEntity.getFormId(), workflowTaskEntity.getCorpid());
            if (formDataList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            PaasFormDataEntityExt formData = formDataList.get(0);
            BeanUtil.copyProperties(formData, processDataEntity);
            processDataEntity.setData(JSON.toJSONString(formData.getData()));

            // 节点模板
            WorkflowNodeEntityExt entityExt = workflowNodeModel.getExtByKey(templateNodeId, corpid);
            if (entityExt == null) {
                LOG.error("workflowNodeId:" + templateNodeId + "  corpid:" + corpid);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_NOT_EXIST);
            }
            summaryEntityList = entityExt.getFieldPermissionList();
            BeanUtil.copyProperties(workflowTaskEntity, paasProcessTaskEntity);
        } else {
            // 任务表
            paasProcessTaskEntity = paasProcessTaskModel.getByKey(coolAppSendCardDTO.getProcessTaskId().intValue(), corpid);
            if (paasProcessTaskEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
            }
            // 获取审批数据
            processDataEntity = paasProcessDataModel.getByTaskId(paasProcessTaskEntity.getId(), corpid);
            if (processDataEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            // 节点模板
            PaasProcessTemplateNodeEntityExt templateNodeEntityExt = paasProcessTemplateNodeModel.getByKey(templateNodeId.intValue(), corpid);
            if (templateNodeEntityExt == null) {
                LOG.error("taskNodeId:" + templateNodeId + "  corpid:" + corpid);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_NOT_EXIST);
            }
            summaryEntityList = templateNodeEntityExt.getFieldPermissionList();
        }
        if (Objects.isNull(paasFormExplainEntity) || Objects.isNull(formEntityExt)) {
            return null;
        }
        Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        List<SummaryDataPoJo> summaryList;
        try {
            // 用户列表
            Map<String, Object> params = BeanUtil.convertBean2Map(coolAppSendCardDTO, true);
            List<UserEntity> allUser = userModel.findEntitys(params);
            if (allUser == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            allUser.forEach((item) -> userMap.put(item.getUserId(), item));
            // 部门列表
            params.remove(ParameterConstant.COLUMNS);
            List<DepartmentEntity> departmentList = departmentModel.findEntitys(params);
            if (departmentList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DEPT_NOT_EXIST);
            }
            Map<String, DepartmentEntity> departmentMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            departmentList.forEach((departmentItem) -> departmentMap.put(departmentItem.getId().toString(), departmentItem));

            SummaryDataDTO summaryDataDTO = new SummaryDataDTO();
            BeanUtil.copyProperties(coolAppSendCardDTO, summaryDataDTO);
            summaryDataDTO.setTaskId(cardDataEntity.getProcessTaskId());
            summaryDataDTO.setMenuId(cardDataEntity.getMenuId());
            summaryDataDTO.setCorpid(corpid);
            summaryDataDTO.setPaasProcessDataEntity(processDataEntity);
            summaryDataDTO.setPaasFormExplainEntity(paasFormExplainEntity);
            summaryDataDTO.setSummaryEntityList(summaryEntityList);
            summaryDataDTO.setUserId(coolAppSendCardDTO.getUserId());
            summaryDataDTO.setUserMap(userMap);
            summaryDataDTO.setDepartmentMap(departmentMap);
            summaryDataDTO.setPaasProcessTaskEntity(paasProcessTaskEntity);
            SummaryDataVO summaryDataVO = processSummaryHelp.getSummaryAndTitle(summaryDataDTO);
            summaryList = summaryDataVO.getSummaryList();
        } catch (XbbException e) {
            summaryList = null;
        }

        // 接收人是否超过20人
        JSONArray cardData = getApprovalSummaryList(summaryList);


        // 创建人
        String creatorId = processDataEntity.getCreatorId();
        UserEntity creatorEntity = userModel.getByKey(creatorId, corpid);

        if (!topCardFlag && Objects.isNull(updatePojo) && Objects.nonNull(receiverUserIdList) && receiverUserIdList.size() > CoolAppConstant.SIMPLE_CARD_USER_NUM){
            return getProcessOrWorkflowSimpleCardData(corpid, cardDataEntity, coolAppSendCardDTO, creatorEntity, processDataEntity, receiverUserIdList, cardProcessWorkflowPojo);
        }

        // 共有数据
        HashMap<String, String> cardDataParamMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        HashMap<String, Object> cardDataParamJson = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        // 标题
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(coolAppSendCardDTO.getBusinessType());
        // todo 国际化
        String title = creatorEntity.getName() + "创建的" + xbbRefTypeEnum.getName() + "审批";
        cardDataParamMap.put("title", title);

        // 吊顶卡片内容
        if (topCardFlag) {
            // 创建人和创建时间
            String addTimeStr = DateTimeUtil.getStringEpochSecond(processDataEntity.getAddTime(), DateTimeUtil.SDFMDHM);
            ItemDataPoJo itemDataPoJo = new ItemDataPoJo("提交人", creatorEntity.getName());
            ItemDataPoJo itemDataPoJo1 = new ItemDataPoJo("创建时间", addTimeStr);
            cardData.clear();
            cardData.add(itemDataPoJo);
            cardData.add(itemDataPoJo1);
            cardDataParamMap.put("topCardType", TopCardTypeEnum.PROCESS_OR_WORKFLOW.getAlias());
            cardDataParamMap.put("rowsNum", "2");
        }
        // 数据摘要
        if (CollectionsUtil.isNotEmpty(cardData)) {
            cardDataParamJson.put("content",cardData);
        }

        Map<String, Map<String, String>> cardPrivateData;
        // 更新数据
        if (Objects.nonNull(updatePojo)) {
            // 拼接私有数据
            cardPrivateData = formatUpdateWorkflowPrivateData(corpid, cardDataEntity, cardProcessWorkflowPojo, updatePojo);
        } else {
            cardPrivateData = formatAddWorkflowPrivateData(corpid, cardDataEntity, cardProcessWorkflowPojo, topCardFlag);
        }

        if (!topCardFlag) {
            // 进度
            String schedule = Objects.isNull(updatePojo) ? cardProcessWorkflowPojo.getApprovalResult() : updatePojo.getApprovalResult();
            // 节点信息 approvalProcess
            JSONArray approvalProcess = new JSONArray();
            CardDataProcessRecord startProcessNode = new CardDataProcessRecord();
            // 提交人
            Long startNodeTaskAddTime = DateTimeUtil.getInt();
            if (startNodeTask instanceof PaasProcessNodeTaskEntityExt) {
                startNodeTaskAddTime = ((PaasProcessNodeTaskEntityExt) startNodeTask).getAddTime();
            } else if (startNodeTask instanceof WorkflowTaskNodeEntity) {
                startNodeTaskAddTime = ((WorkflowTaskNodeEntity) startNodeTask).getAddTime();
            }
            startProcessNode.setName(creatorEntity.getName());
            startProcessNode.setSchedule("发起申请");
            startProcessNode.setTime(DateTimeUtil.getStringEpochSecond(startNodeTaskAddTime, DateTimeUtil.SDFMDHM));
            // 头像为空，默认头像
            String creatorAvatar = StringUtil.isNotEmpty(creatorEntity.getAvatar()) ?  creatorEntity.getAvatar() : CoolAppConstant.DEFAULT_USER_AVATAR;
            startProcessNode.setImg(creatorAvatar);
            approvalProcess.add(startProcessNode);
            // 审批人节点
            StringBuilder approvalNameBuilder = new StringBuilder();
            String approvalTime = DateTimeUtil.getString();
            String approvalAvatar = null;
            for (Map.Entry<String, Object> entry : mainProcessNodeTaskMap.entrySet()) {

                UserEntity userEntity = userMap.get(entry.getKey());
                if (approvalNameBuilder.length() == BasicConstant.ZERO) {
                    approvalNameBuilder.append(userEntity.getName());
                    Long nodeTaskUpdateTime = DateTimeUtil.getInt();
                    Object value = entry.getValue();
                    if (value instanceof PaasProcessNodeTaskEntityExt) {
                        nodeTaskUpdateTime = ((PaasProcessNodeTaskEntityExt) value).getUpdateTime();
                    } else if (value instanceof WorkflowTaskNodeEntity) {
                        nodeTaskUpdateTime = ((WorkflowTaskNodeEntity) value).getUpdateTime();
                    }
                    approvalTime = DateTimeUtil.getStringEpochSecond(nodeTaskUpdateTime, DateTimeUtil.SDFMDHM);
                } else {
                    approvalNameBuilder.append("、").append(userEntity.getName());
                }
                if (Objects.isNull(approvalAvatar)) {
                    approvalAvatar = userEntity.getAvatar();
                }
            }
            if (mainProcessNodeTaskMap.size() > BasicConstant.ONE) {
                approvalAvatar = "";
            }
            // 默认头像
            if (StringUtil.isEmpty(approvalAvatar)) {
                approvalAvatar = CoolAppConstant.DEFAULT_USER_AVATAR;
            }
            CardDataProcessRecord approvalProcessNode = new CardDataProcessRecord();

            approvalProcessNode.setSchedule(schedule);
            approvalProcessNode.setName(approvalNameBuilder.toString());
            approvalProcessNode.setTime(approvalTime);
            approvalProcessNode.setImg(approvalAvatar);
            approvalProcess.add(approvalProcessNode);
            cardDataParamJson.put("approvalProcess", approvalProcess);

        }

        cardDataParamMap.put(CoolAppConstant.COMPLEX_PARAM, JSON.toJSONString(cardDataParamJson));

        // 对象 数组等复杂数据固定格式
        return new CardDataPojo(receiverUserIdList, cardDataParamMap, cardPrivateData);
    }

    /***
     * 获取审批工作流极简卡片内容
     *
     * @param corpid
     * @param: cardDataEntity
     * @param: coolAppSendCardDTO
     * @param: creatorEntity
     * @param: processDataEntity
     * @param: receiverUserIdList
     * @param: cardProcessWorkflowPojo
     * @throws
     * @return com.xbongbong.pro.coolapp.pojo.CardDataPojo
     * @author hongxiao
     * @date 2022-10-20 16:48
     * @since
     * @version
     */
    private CardDataPojo getProcessOrWorkflowSimpleCardData(String corpid, CoolAppCardDataEntity cardDataEntity,CoolAppSendCardDTO coolAppSendCardDTO,
                                                            UserEntity creatorEntity, PaasProcessDataEntity processDataEntity, List<String> receiverUserIdList,
                                                            CardProcessWorkflowPojo cardProcessWorkflowPojo) {
        HashMap<String, String> cardDataParamMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Map<String, String>> cardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(coolAppSendCardDTO.getBusinessType());
        String title1 = "您有一条新审批";
        String name = creatorEntity.getName();
        String data = processDataEntity.getData();
        JSONObject o =  JSONObject.parseObject(data);
        String content = "";
        switch (xbbRefTypeEnum){
            case CUSTOMER_MANAGEMENT:
                content = "\"" + name + "\"" + "提交了一个" + xbbRefTypeEnum.getName() + "\"" +o.getString(CustomerManagementEnum.NAME.getAttr())+ "\"" + ", 请及时审批";
                break;
            case SALES_OPPORTUNITY:
                content = "\"" + name + "\"" + "提交了一个" + xbbRefTypeEnum.getName() + "\"" +o.getString(SalesOpportunityEnum.NAME.getAttr())+ "\"" + ", 请及时审批";
                break;
            default:
                break;
        }
        cardDataParamMap.put("title", title1);
        cardDataParamMap.put("simpleContent", content);
        for (String userId : receiverUserIdList) {
            CardDataProcessNode dataProcessNode = cardProcessWorkflowPojo.getProcessNode();
            Map<String, Long> mainNodeTaskIdMap = dataProcessNode.getApproval();
            Map<String, Long> creatorNodeTaskIdMap = dataProcessNode.getCreator();
            Map<String, Long> ccNodeTaskIdMap = dataProcessNode.getCc();
            Long nodeTaskId = 0L;
            String processType = "";
            if (Objects.nonNull(mainNodeTaskIdMap) && mainNodeTaskIdMap.containsKey(userId)) {
                nodeTaskId = mainNodeTaskIdMap.get(userId);
                processType = ProcessTypeEnum.TODO.getValue();
            } else if (Objects.nonNull(creatorNodeTaskIdMap) && creatorNodeTaskIdMap.containsKey(userId)) {
                nodeTaskId = creatorNodeTaskIdMap.get(userId);
                processType = ProcessTypeEnum.CREATE.getValue();
            } else if (Objects.nonNull(ccNodeTaskIdMap) && ccNodeTaskIdMap.containsKey(userId)) {
                nodeTaskId = ccNodeTaskIdMap.get(userId);
                processType = ProcessTypeEnum.CC.getValue();
            }
            Map<String, Object> tempCardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, String> tempCardPrivateData1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            String detailUrl = formatProcessButtonsLinkUrl(corpid, cardProcessWorkflowPojo.getWorkflow(), cardDataEntity, nodeTaskId, processType);
            String pcDetailUrl = CoolAppConstant.DINGTALK_PC_URL + URLEncodeUtils.encodeURL(detailUrl);
            String mobileDetailUrl = CoolAppConstant.DINGTALK_MOBILE_URL + URLEncodeUtils.encodeURL(detailUrl);
            JSONObject buttons = getWorkflowButtons(pcDetailUrl, mobileDetailUrl);
            tempCardPrivateData.put("buttons", buttons);
            tempCardPrivateData1.put(CoolAppConstant.COMPLEX_PARAM, JSON.toJSONString(tempCardPrivateData));

            cardPrivateData.put(userId, tempCardPrivateData1);

        }
        return new CardDataPojo(receiverUserIdList, cardDataParamMap, cardPrivateData);
    }

    /**
     * 保存卡片发送相关数据
     *
     * @param coolAppSendCardDTO
     * @param cardId
     * @param receiverUserIds
     * @param creatorId
     * @param parentCardBizId
     * @param sourceDataId
     * @param processNode
     * @return
     */
    @Override
    public CoolAppCardDataEntity saveCardData(CoolAppSendCardDTO coolAppSendCardDTO,String cardId,JSONArray receiverUserIds, String creatorId, String parentCardBizId, Long sourceDataId, JSONObject processNode) throws XbbException {
        CoolAppCardDataEntity cardDataEntity = new CoolAppCardDataEntity();
        cardDataEntity.setCorpid(coolAppSendCardDTO.getCorpid());
        cardDataEntity.setAppId(coolAppSendCardDTO.getAppId());
        cardDataEntity.setMenuId(coolAppSendCardDTO.getMenuId());
        cardDataEntity.setFormId(coolAppSendCardDTO.getFormId());
        cardDataEntity.setSaasMark(coolAppSendCardDTO.getSaasMark());
        cardDataEntity.setBusinessType(coolAppSendCardDTO.getBusinessType());
        cardDataEntity.setDataId(coolAppSendCardDTO.getDataId());
        cardDataEntity.setProcessTaskId(coolAppSendCardDTO.getProcessTaskId());
        cardDataEntity.setProcessNodeTaskId(coolAppSendCardDTO.getProcessNodeTaskId());
        cardDataEntity.setFlowStatus(coolAppSendCardDTO.getFlowStatus());
        cardDataEntity.setCreatorId(creatorId);
        // 审批节点对应模板
        cardDataEntity.setProcessNode(processNode);

        // 开启跟进提醒保存关联客户数据id
        cardDataEntity.setSourceDataId(sourceDataId);

        cardDataEntity.setCardId(cardId);
        cardDataEntity.setOpenConversationId(coolAppSendCardDTO.getOpenConversationId());
        cardDataEntity.setConversationType(BasicConstant.ONE);
        cardDataEntity.setRobotCode(proBaseConfig.getRobotCode());
        cardDataEntity.setCardBizId(UUID.randomUUID().toString());
        // parentCardBizId，默认为1
        cardDataEntity.setParentCardBizId(BasicConstant.ONE_STRING);
        if (Objects.nonNull(parentCardBizId)) {
            cardDataEntity.setParentCardBizId(parentCardBizId);
        }
        // 卡片接收人
        cardDataEntity.setReceiverUserIds(receiverUserIds);
        // 消息@人
        cardDataEntity.setAtUserIds(null);
        try {
            coolAppCardDataModel.insert(cardDataEntity);
        } catch (Exception e) {
            LOG.error("保存互动卡片失败！",e );
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, I18nMessageUtil.getMessage(ErrorMessageConstant.SAVE_ERROR));
        }
        return cardDataEntity;

    }

    @Override
    public CardProcessWorkflowPojo getProcessOrWorkflow(CoolAppWorkflowCardDTO coolAppWorkflowCardDTO, boolean workflow, boolean isEnd) throws XbbException {
        String corpid = coolAppWorkflowCardDTO.getCorpid();
        Long taskId = coolAppWorkflowCardDTO.getTaskId();
        Long formId = coolAppWorkflowCardDTO.getFormId();

        Long processNodeTaskId = null;
        String startNodeUserId;
        Object startNodeTask;
        Map<String, Long> mainProcessIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Long> ccProcessIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Long> creatorProcessIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Object> mainProcessMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Object> ccProcessMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> mainUserIds = new ArrayList<>();
        List<String> ccUserIds = new ArrayList<>();

        CardProcessWorkflowPojo processWorkflowPojo = new CardProcessWorkflowPojo();

        if (workflow){
            // 开始节点
            WorkflowTaskNodeEntity workflowStartNodeTask = workflowTaskNodeModel.getWorkflowStartNodeTask(corpid, coolAppWorkflowCardDTO.getFormId(), taskId, coolAppWorkflowCardDTO.getWorkflowId());
            if (Objects.isNull(workflowStartNodeTask)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            // 当前任务节点
            List<WorkflowTaskNodeEntity> workflowTaskNodeList = getWorkflowNodeTask(corpid, coolAppWorkflowCardDTO.getFormId(), taskId, coolAppWorkflowCardDTO.getWorkflowId());
            if (CollectionsUtil.isEmpty(workflowTaskNodeList)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            for (WorkflowTaskNodeEntity taskNode : workflowTaskNodeList) {
                if (Objects.equals(taskNode.getTaskType(), TaskTypeEnum.CC.getType())) {
                    ccProcessMap.put(taskNode.getUserId(), taskNode);
                    ccProcessIdMap.put(taskNode.getUserId(), taskNode.getId());
                    ccUserIds.add(taskNode.getUserId());
                } else {
                    mainProcessMap.put(taskNode.getUserId(), taskNode);
                    mainProcessIdMap.put(taskNode.getUserId(), taskNode.getId());
                    mainUserIds.add(taskNode.getUserId());
                    if (Objects.isNull(processNodeTaskId)) {
                        processNodeTaskId = taskNode.getId();
                    }
                }
            }

            creatorProcessIdMap.put(workflowStartNodeTask.getUserId(), workflowStartNodeTask.getId());
            processWorkflowPojo.setStartNodeTask(workflowStartNodeTask);
            startNodeUserId = workflowStartNodeTask.getUserId();
            startNodeTask = workflowStartNodeTask;
        } else {
            // 开始节点
            PaasProcessNodeTaskEntityExt processStartNodeTask = getStartNodeTask(corpid, formId, taskId);
            if (Objects.isNull(processStartNodeTask)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }


            // 获取审批节点
            List<PaasProcessNodeTaskEntityExt> nodeTaskList = getNodeTaskList(coolAppWorkflowCardDTO.getCorpid(), coolAppWorkflowCardDTO.getFormId(), taskId);
            if (CollectionsUtil.isEmpty(nodeTaskList)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            for (PaasProcessNodeTaskEntityExt nodeTaskEntityExt : nodeTaskList) {
                if (Objects.equals(nodeTaskEntityExt.getTaskType(), TaskTypeEnum.CC.getType())) {
                    ccProcessMap.put(nodeTaskEntityExt.getUserId(), nodeTaskEntityExt);
                    ccProcessIdMap.put(nodeTaskEntityExt.getUserId(), nodeTaskEntityExt.getId());
                    ccUserIds.add(nodeTaskEntityExt.getUserId());
                } else {
                    mainProcessMap.put(nodeTaskEntityExt.getUserId(), nodeTaskEntityExt);
                    mainProcessIdMap.put(nodeTaskEntityExt.getUserId(), nodeTaskEntityExt.getId());
                    mainUserIds.add(nodeTaskEntityExt.getUserId());
                    if (Objects.isNull(processNodeTaskId)) {
                        processNodeTaskId = nodeTaskEntityExt.getId();
                    }
                }
            }
            creatorProcessIdMap.put(processStartNodeTask.getUserId(), processStartNodeTask.getId());
            startNodeUserId = processStartNodeTask.getUserId();
            startNodeTask = processStartNodeTask;
        }

        // 节点信息
        processWorkflowPojo.getProcessNode().setApproval(mainProcessIdMap);
        processWorkflowPojo.getProcessNode().setCreator(creatorProcessIdMap);
        processWorkflowPojo.getProcessNode().setCc(ccProcessIdMap);


        processWorkflowPojo.setWorkflow(workflow);
        // 节点
        processWorkflowPojo.setProcessNodeTaskId(processNodeTaskId);
        processWorkflowPojo.setStartNodeTask(startNodeTask);
        processWorkflowPojo.setStartNodeUserId(startNodeUserId);
        processWorkflowPojo.setMainProcessMap(mainProcessMap);
        processWorkflowPojo.setCcProcessMap(ccProcessMap);
        // 节点人员
        processWorkflowPojo.setMainUserIds(mainUserIds);
        processWorkflowPojo.setCcUserIds(ccUserIds);
        // 状态
        processWorkflowPojo.setApprovalResult(CoolAppConstant.IN_APPROVAL);
        if (isEnd) {
            processWorkflowPojo.setApprovalResult(CoolAppConstant.PAAS);
        }

        return processWorkflowPojo;
    }



    /**
     * 工作流未处理节点、抄送节点
     *
     * @param corpid
     * @param formId
     * @param taskId
     * @param workflowId
     * @return
     */
    private List<WorkflowTaskNodeEntity> getWorkflowNodeTask(String corpid, Long formId, Long taskId, Long workflowId) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.FORMID, formId);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("taskId", taskId);
        param.put("workflowId", workflowId);
        param.put("taskTypeIn", Arrays.asList(TaskTypeEnum.UNTREATED.getType(), TaskTypeEnum.CC.getType()));
        param.put(ParameterConstant.ORDER_BY_STR, "update_time desc, id desc");
        // 回退后上一节点分有几个，需要处理节点
        List<WorkflowTaskNodeEntity> list = workflowTaskNodeModel.findEntities(param);
        Set<String> mainUserIdSet = new HashSet<>();
        Set<String> ccUserIdSet = new HashSet<>();
        List<WorkflowTaskNodeEntity> resultList = new ArrayList<>();
        for (WorkflowTaskNodeEntity entityExt : list) {
            String userId = entityExt.getUserId();
            if (Objects.equals(TaskTypeEnum.UNTREATED.getType(), entityExt.getTaskType())) {
                if (mainUserIdSet.contains(userId)) {
                    continue;
                }
                mainUserIdSet.add(userId);
                resultList.add(entityExt);
            } else if (Objects.equals(TaskTypeEnum.CC.getType(), entityExt.getTaskType())) {
                if (ccUserIdSet.contains(userId)) {
                    continue;
                }
                ccUserIdSet.add(userId);
                resultList.add(entityExt);
            }
        }

        return resultList;
    }


    /**
     * 审批开始节点
     *
     * @param corpid
     * @param formId
     * @param taskId
     * @return
     */
    private PaasProcessNodeTaskEntityExt getStartNodeTask(String corpid, Long formId, Long taskId) {
        // 查找开始节点
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        // 当前审批节点
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("nodeType", NodeTypeEnum.START_PROCESS_NODE.getNodeType());
        params.put("taskId", taskId);
        params.put("formId", formId);

        List<PaasProcessNodeTaskEntityExt> startNodeList = paasProcessNodeTaskModel.findEntitys(params);
        return CollectionsUtil.isEmpty(startNodeList) ? null : startNodeList.get(0);
    }

    /**
     * 审批未处理节点、抄送节点
     *
     * @param corpid
     * @param formId
     * @param taskId
     * @return
     */
    private List<PaasProcessNodeTaskEntityExt> getNodeTaskList(String corpid, Long formId, Long taskId) {

        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("taskId", taskId);
        params.put("formId", formId);
        params.put("taskTypeIn", Arrays.asList(TaskTypeEnum.UNTREATED.getType(), TaskTypeEnum.CC.getType()));
        params.put("orderByStr", "update_time desc");
        // 回退后上一节点分有几个，需要处理节点
        List<PaasProcessNodeTaskEntityExt> list = paasProcessNodeTaskModel.findEntitys(params);
        Set<String> mainUserIdSet = new HashSet<>();
        Set<String> ccUserIdSet = new HashSet<>();
        List<PaasProcessNodeTaskEntityExt> resultList = new ArrayList<>();
        for (PaasProcessNodeTaskEntityExt entityExt : list) {
            String userId = entityExt.getUserId();
            if (Objects.equals(TaskTypeEnum.UNTREATED.getType(), entityExt.getTaskType())) {
                if (mainUserIdSet.contains(userId)) {
                    continue;
                }
                mainUserIdSet.add(userId);
                resultList.add(entityExt);
            } else if (Objects.equals(TaskTypeEnum.CC.getType(), entityExt.getTaskType())) {
                if (ccUserIdSet.contains(userId)) {
                    continue;
                }
                ccUserIdSet.add(userId);
                resultList.add(entityExt);
            }
        }
        return resultList;
    }

    /**
     * 获取节点模板id
     *
     * @param nodeTaskId
     * @param mainProcessNodeTaskMap
     * @param ccProcessNodeTaskMap
     * @param notMainNodeFlag
     * @param notCcNodeFlag
     * @return
     */
    private Long getTemplateNodeId(Long nodeTaskId, Map<String, Object> mainProcessNodeTaskMap, Map<String, Object> ccProcessNodeTaskMap, boolean notMainNodeFlag, boolean notCcNodeFlag) {
        Long templateNodeId = 0L;
        if (!notMainNodeFlag) {
            for (Map.Entry<String, Object> entry : mainProcessNodeTaskMap.entrySet()) {
                Object value = entry.getValue();
                if (value instanceof PaasProcessNodeTaskEntityExt) {
                    if (Objects.equals(nodeTaskId, ((PaasProcessNodeTaskEntityExt) value).getId())) {
                        return  ((PaasProcessNodeTaskEntityExt) value).getTemplateNodeId();
                    }
                } else if (value instanceof WorkflowTaskNodeEntity) {
                    if (Objects.equals(nodeTaskId, ((WorkflowTaskNodeEntity) value).getId())) {
                        return  ((WorkflowTaskNodeEntity) value).getWorkflowNodeId();
                    }
                }
            }
        } else if (!notCcNodeFlag) {
            for (Map.Entry<String, Object> entry : ccProcessNodeTaskMap.entrySet()) {
                Object value = entry.getValue();
                if (value instanceof PaasProcessNodeTaskEntityExt) {
                    if (Objects.equals(nodeTaskId, ((PaasProcessNodeTaskEntityExt) value).getId())) {
                        return  ((PaasProcessNodeTaskEntityExt) value).getTemplateNodeId();
                    }
                } else if (value instanceof WorkflowTaskNodeEntity) {
                    if (Objects.equals(nodeTaskId, ((WorkflowTaskNodeEntity) value).getId())) {
                        return  ((WorkflowTaskNodeEntity) value).getWorkflowNodeId();
                    }
                }
            }
        }
        return templateNodeId;
    }


    public JSONArray getApprovalSummaryList(List<SummaryDataPoJo> summaryList)  {
        if (CollectionsUtil.isEmpty(summaryList)) {
            return new JSONArray();
        }
        JSONArray resultList = new JSONArray();
        for (SummaryDataPoJo dataPoJo : summaryList) {
            List<Object> values = dataPoJo.getValue();
            String val = "";
            ItemDataPoJo itemDataPoJo;
            if (CollectionsUtil.isNotEmpty(values)){
                for (Object value : values) {
                    String s = String.valueOf(value);
                    val = val + s + ",";
                }
                String s = val.substring(0, val.length() - 1);
                itemDataPoJo = new ItemDataPoJo(dataPoJo.getAttrName(), s);
            }else {
                itemDataPoJo = new ItemDataPoJo(dataPoJo.getAttrName(), "");
            }
            resultList.add(itemDataPoJo);
        }
        return resultList;
    }

    /**
     * 拼接提交审批时私有数据
     *
     * @param corpid
     * @param cardDataEntity
     * @param cardProcessWorkflowPojo
     * @param topCardFlag
     * @return
     */
    private Map<String, Map<String, String>> formatAddWorkflowPrivateData(String corpid, CoolAppCardDataEntity cardDataEntity,
                                                                          CardProcessWorkflowPojo cardProcessWorkflowPojo, boolean topCardFlag) {
        Map<String, Map<String, String>> cardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        boolean workFlow = cardProcessWorkflowPojo.getWorkflow();
        CardDataProcessNode dataProcessNode = cardProcessWorkflowPojo.getProcessNode();
        Map<String, Long> mainNodeTaskIdMap = dataProcessNode.getApproval();
        Map<String, Long> creatorNodeTaskIdMap = dataProcessNode.getCreator();
        Map<String, Long> ccNodeTaskIdMap = dataProcessNode.getCc();

        if (!topCardFlag) {
            // 抄送人
            if (Objects.nonNull(ccNodeTaskIdMap)) {
                ccNodeTaskIdMap.forEach((userId, nodeTaskId) -> {
                    String detailUrl = formatProcessButtonsLinkUrl(corpid, workFlow, cardDataEntity, nodeTaskId, ProcessTypeEnum.CC.getValue());
                    String pcDetailUrl = CoolAppConstant.DINGTALK_PC_URL + URLEncodeUtils.encodeURL(detailUrl);
                    String mobileDetailUrl = CoolAppConstant.DINGTALK_MOBILE_URL + URLEncodeUtils.encodeURL(detailUrl);
                    JSONObject buttons = getWorkflowButtons(pcDetailUrl, mobileDetailUrl);

                    Map<String, Object> tempCardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Map<String, String> tempCardPrivateData1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    tempCardPrivateData.put("buttons", buttons);
                    tempCardPrivateData1.put(CoolAppConstant.COMPLEX_PARAM, JSON.toJSONString(tempCardPrivateData));
                    cardPrivateData.put(userId, tempCardPrivateData1);
                });
            }
            // 提交人
            if (Objects.nonNull(creatorNodeTaskIdMap)) {
                String creatorId = "";
                Long startNodeTaskId = 0L;
                for (Map.Entry<String, Long> entry : creatorNodeTaskIdMap.entrySet()) {
                    creatorId = entry.getKey();
                    startNodeTaskId = entry.getValue();
                    break;
                }
                String detailUrl = formatProcessButtonsLinkUrl(corpid, workFlow, cardDataEntity, startNodeTaskId, ProcessTypeEnum.CREATE.getValue());
                String pcDetailUrl = CoolAppConstant.DINGTALK_PC_URL + URLEncodeUtils.encodeURL(detailUrl);
                String mobileDetailUrl = CoolAppConstant.DINGTALK_MOBILE_URL + URLEncodeUtils.encodeURL(detailUrl);
                JSONObject buttons = getWorkflowButtons(pcDetailUrl, mobileDetailUrl);

                Map<String, Object> tempCardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<String, String> tempCardPrivateData1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                tempCardPrivateData.put("buttons", buttons);
                tempCardPrivateData1.put(CoolAppConstant.COMPLEX_PARAM, JSON.toJSONString(tempCardPrivateData));
                cardPrivateData.put(creatorId, tempCardPrivateData1);
            }
        }

        // 审批人
        if (Objects.nonNull(mainNodeTaskIdMap)) {
            mainNodeTaskIdMap.forEach((userId, nodeTaskId) -> {
                String detailUrl = formatProcessButtonsLinkUrl(corpid, workFlow, cardDataEntity, nodeTaskId, ProcessTypeEnum.TODO.getValue());
                String pcDetailUrl = CoolAppConstant.DINGTALK_PC_URL + URLEncodeUtils.encodeURL(detailUrl);
                String mobileDetailUrl = CoolAppConstant.DINGTALK_MOBILE_URL + URLEncodeUtils.encodeURL(detailUrl);
                JSONObject buttons = getWorkflowButtons(pcDetailUrl, mobileDetailUrl);

                Map<String, Object> tempCardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<String, String> tempCardPrivateData1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                tempCardPrivateData.put("buttons", buttons);
                tempCardPrivateData1.put(CoolAppConstant.COMPLEX_PARAM, JSON.toJSONString(tempCardPrivateData));
                cardPrivateData.put(userId, tempCardPrivateData1);
            });
        }
        return cardPrivateData;
    }

    /**
     * 拼接审批操作时私有数据
     *
     * @param corpid
     * @param cardDataEntity
     * @param cardProcessWorkflowPojo
     * @param updatePojo
     * @return
     */
    private Map<String, Map<String, String>> formatUpdateWorkflowPrivateData(String corpid, CoolAppCardDataEntity cardDataEntity,
                                                                             CardProcessWorkflowPojo cardProcessWorkflowPojo, CardDataProcessUpdatePojo updatePojo) {
        Map<String, Map<String, String>> cardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> receiverUserIds = cardDataEntity.getReceiverUserIds().toJavaList(String.class);

        FlowStatusEnum flowStatusEnum = FlowStatusEnum.getFlowStatusEnumByType(updatePojo.getFlowStatus());

        boolean workFlow = cardProcessWorkflowPojo.getWorkflow();
        CardDataProcessNode dataProcessNode = cardProcessWorkflowPojo.getProcessNode();
        Map<String, Long> mainNodeTaskIdMap = dataProcessNode.getApproval();
        Map<String, Long> creatorNodeTaskIdMap = dataProcessNode.getCreator();
        Map<String, Long> ccNodeTaskIdMap = dataProcessNode.getCc();

        for (String userId : receiverUserIds) {
            Long nodeTaskId = 0L;
            String processType = "";
            if (Objects.nonNull(mainNodeTaskIdMap) && mainNodeTaskIdMap.containsKey(userId)) {
                nodeTaskId = mainNodeTaskIdMap.get(userId);
                processType = ProcessTypeEnum.TODO.getValue();
            } else if (Objects.nonNull(creatorNodeTaskIdMap) && creatorNodeTaskIdMap.containsKey(userId)) {
                nodeTaskId = creatorNodeTaskIdMap.get(userId);
                processType = ProcessTypeEnum.CREATE.getValue();
            } else if (Objects.nonNull(ccNodeTaskIdMap) && ccNodeTaskIdMap.containsKey(userId)) {
                nodeTaskId = ccNodeTaskIdMap.get(userId);
                processType = ProcessTypeEnum.CC.getValue();
            }
            String detailUrl = formatProcessButtonsLinkUrl(corpid, workFlow, cardDataEntity, nodeTaskId, processType);
            String pcDetailUrl = CoolAppConstant.DINGTALK_PC_URL + URLEncodeUtils.encodeURL(detailUrl);
            String mobileDetailUrl = CoolAppConstant.DINGTALK_MOBILE_URL + URLEncodeUtils.encodeURL(detailUrl);
            Map<String, Object> tempCardPrivateData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, String> tempCardPrivateData1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (FlowStatusEnum.REJECT == flowStatusEnum) {
                tempCardPrivateData.put("approvalResult", CoolAppConstant.REFUSED);
            } else {
                if (Objects.equals(userId, updatePojo.getOperatorId())) {
                    tempCardPrivateData.put("approvalResult", CoolAppConstant.I_HAVE_BEEN + updatePojo.getApprovalResult());
                } else {
                    tempCardPrivateData.put("approvalResult", updatePojo.getApprovalResult());
                }
            }
            JSONObject buttons = getWorkflowButtons(pcDetailUrl, mobileDetailUrl);
            tempCardPrivateData.put("buttons", buttons);
            tempCardPrivateData1.put(CoolAppConstant.COMPLEX_PARAM, JSON.toJSONString(tempCardPrivateData));

            cardPrivateData.put(userId, tempCardPrivateData1);
        }
        return cardPrivateData;
    }


    /**
     * 拼接审批按钮链接
     *
     * @param corpid
     * @param workFlow
     * @param cardDataEntity
     * @param processNodeTaskId
     * @param processType
     * @return
     */
    private String formatProcessButtonsLinkUrl(String corpid, boolean workFlow, CoolAppCardDataEntity cardDataEntity, Long processNodeTaskId, String processType) {
        String linkUrl = proBaseConfig.getPushFrontUrl() + "index.html?corpid=" + corpid + "&appid=" + Env.DING_XBB_APP_ID + "&openConversationId=" + cardDataEntity.getOpenConversationId() + "#";
        if (workFlow) {
            linkUrl += String.format(DingtalkPageUrlEnum.WORKFLOW_DETAIL.getUrl(), cardDataEntity.getProcessTaskId(), processNodeTaskId, cardDataEntity.getAppId(), cardDataEntity.getMenuId(), cardDataEntity.getFormId(), cardDataEntity.getSaasMark(), cardDataEntity.getBusinessType(), processType);
        } else {
            linkUrl += String.format(DingtalkPageUrlEnum.APPROVAL_DETAIL.getUrl(), cardDataEntity.getProcessTaskId(), processNodeTaskId, cardDataEntity.getAppId(), cardDataEntity.getMenuId(), cardDataEntity.getFormId(), cardDataEntity.getSaasMark(), cardDataEntity.getBusinessType(), processType);
        }
        return linkUrl;
    }

    /**
     * 获取审批按钮
     *
     * @param pcDetailUrl
     * @param mobileDetailUrl
     * @return
     */
    private JSONObject getWorkflowButtons(String pcDetailUrl, String mobileDetailUrl) {
        // 按钮添加url
        JSONObject detail = new JSONObject();
        JSONObject buttons = new JSONObject();
        detail.put("pcUrl", pcDetailUrl);
        detail.put("mobileUrl", mobileDetailUrl);

        detail.put("name", "查看详情");
        buttons.put("detail", detail);

        return buttons;
    }

}
